Skip to content

Commit

Permalink
[firrtl] Add 4.0.0 public modules
Browse files Browse the repository at this point in the history
Add support for FIRRTL 4.0.0 feature, "public modules".  This does not
provide complete FIRRTL 4.0.0 support as this requires removing circuit
names.  This will be done in a later commit.

Signed-off-by: Schuyler Eldridge <schuyler.eldridge@sifive.com>
  • Loading branch information
seldridge committed Nov 28, 2023
1 parent 4da1ade commit 30a0274
Show file tree
Hide file tree
Showing 4 changed files with 59 additions and 20 deletions.
53 changes: 33 additions & 20 deletions lib/Dialect/FIRRTL/Import/FIRParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4111,7 +4111,7 @@ struct FIRCircuitParser : public FIRParser {
ParseResult parseExtClass(CircuitOp circuit, unsigned indent);
ParseResult parseExtModule(CircuitOp circuit, unsigned indent);
ParseResult parseIntModule(CircuitOp circuit, unsigned indent);
ParseResult parseModule(CircuitOp circuit, unsigned indent);
ParseResult parseModule(CircuitOp circuit, bool isPublic, unsigned indent);

ParseResult parsePortList(SmallVectorImpl<PortInfo> &resultPorts,
SmallVectorImpl<SMLoc> &resultPortLocs,
Expand Down Expand Up @@ -4368,6 +4368,7 @@ ParseResult FIRCircuitParser::skipToModuleEnd(unsigned indent) {
case FIRToken::kw_extmodule:
case FIRToken::kw_intmodule:
case FIRToken::kw_module:
case FIRToken::kw_public:
case FIRToken::kw_layer:
case FIRToken::kw_type:
// All module declarations should have the same indentation
Expand Down Expand Up @@ -4497,6 +4498,7 @@ ParseResult FIRCircuitParser::parseClass(CircuitOp circuit, unsigned indent) {
// build it
auto builder = circuit.getBodyBuilder();
auto classOp = builder.create<ClassOp>(info.getLoc(), name, portList);
classOp.setPrivate();
deferredModules.emplace_back(
DeferredModuleToParse{classOp, portLocs, getLexer().getCursor(), indent});

Expand Down Expand Up @@ -4569,13 +4571,20 @@ ParseResult FIRCircuitParser::parseExtModule(CircuitOp circuit,
return failure();

auto builder = circuit.getBodyBuilder();
auto convention = getConstants().options.scalarizeExtModules
? Convention::Scalarized
: Convention::Internal;
auto isMainModule = (name == circuit.getName());
auto convention =
(isMainModule && getConstants().options.scalarizeTopModule) ||
getConstants().options.scalarizeExtModules
? Convention::Scalarized
: Convention::Internal;
auto conventionAttr = ConventionAttr::get(getContext(), convention);
auto annotations = ArrayAttr::get(getContext(), {});
builder.create<FExtModuleOp>(info.getLoc(), name, conventionAttr, portList,
defName, annotations, parameters, internalPaths);
auto extModuleOp = builder.create<FExtModuleOp>(
info.getLoc(), name, conventionAttr, portList, defName, annotations,
parameters, internalPaths);
auto visibility = isMainModule ? SymbolTable::Visibility::Public
: SymbolTable::Visibility::Private;
SymbolTable::setSymbolVisibility(extModuleOp, visibility);
return success();
}

Expand Down Expand Up @@ -4609,13 +4618,16 @@ ParseResult FIRCircuitParser::parseIntModule(CircuitOp circuit,

ArrayAttr annotations = getConstants().emptyArrayAttr;
auto builder = circuit.getBodyBuilder();
builder.create<FIntModuleOp>(info.getLoc(), name, portList, intName,
annotations, parameters, internalPaths);
builder
.create<FIntModuleOp>(info.getLoc(), name, portList, intName, annotations,
parameters, internalPaths)
.setPrivate();
return success();
}

/// module ::= 'module' id ':' info? INDENT portlist simple_stmt_block DEDENT
ParseResult FIRCircuitParser::parseModule(CircuitOp circuit, unsigned indent) {
ParseResult FIRCircuitParser::parseModule(CircuitOp circuit, bool isPublic,
unsigned indent) {
StringAttr name;
SmallVector<PortInfo, 8> portList;
SmallVector<SMLoc> portLocs;
Expand All @@ -4636,8 +4648,9 @@ ParseResult FIRCircuitParser::parseModule(CircuitOp circuit, unsigned indent) {
auto builder = circuit.getBodyBuilder();
auto moduleOp = builder.create<FModuleOp>(info.getLoc(), name, conventionAttr,
portList, annotations);
auto visibility = isMainModule ? SymbolTable::Visibility::Public
: SymbolTable::Visibility::Private;

auto visibility = isMainModule || isPublic ? SymbolTable::Visibility::Public
: SymbolTable::Visibility::Private;
SymbolTable::setSymbolVisibility(moduleOp, visibility);

// Parse the body of this module after all prototypes have been parsed. This
Expand Down Expand Up @@ -4671,7 +4684,14 @@ ParseResult FIRCircuitParser::parseToplevelDefinition(CircuitOp circuit,
return failure();
return parseLayer(circuit);
case FIRToken::kw_module:
return parseModule(circuit, indent);
return parseModule(circuit, /*isPublic=*/false, indent);
case FIRToken::kw_public:
if (requireFeature({4, 0, 0}, "public modules"))
return failure();
consumeToken();
if (getToken().getKind() == FIRToken::kw_module)
return parseModule(circuit, /*isPublic=*/true, indent);
return emitError(getToken().getLoc(), "only modules may be public");
case FIRToken::kw_type:
return parseTypeDecl();
default:
Expand Down Expand Up @@ -4935,6 +4955,7 @@ ParseResult FIRCircuitParser::parseCircuit(
case FIRToken::kw_intmodule:
case FIRToken::kw_layer:
case FIRToken::kw_module:
case FIRToken::kw_public:
case FIRToken::kw_type: {
auto indent = getIndentation();
if (!indent.has_value())
Expand Down Expand Up @@ -4986,14 +5007,6 @@ ParseResult FIRCircuitParser::parseCircuit(
<< "' must contain a module named '" << circuit.getName() << "'";
}

// If the circuit has an entry point that is not an external module, set the
// visibility of all non-main modules to private.
if (auto mainMod = dyn_cast<FModuleOp>(*main)) {
for (auto mod : circuit.getOps<FModuleLike>()) {
if (mod != main)
SymbolTable::setSymbolVisibility(mod, SymbolTable::Visibility::Private);
}
}
return success();
}

Expand Down
1 change: 1 addition & 0 deletions lib/Dialect/FIRRTL/Import/FIRTokenKinds.def
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@ TOK_KEYWORD(old)
TOK_KEYWORD(output)
TOK_KEYWORD(parameter)
TOK_KEYWORD(propassign)
TOK_KEYWORD(public)
TOK_KEYWORD(rdwr)
TOK_KEYWORD(read)
TOK_KEYWORD(ref)
Expand Down
12 changes: 12 additions & 0 deletions test/Dialect/FIRRTL/parse-basic.fir
Original file line number Diff line number Diff line change
Expand Up @@ -1863,3 +1863,15 @@ circuit AnyRef:
; CHECK-NEXT: %[[CAST:.+]] = firrtl.object.anyref_cast %[[OBJ]]
; CHECK-NEXT: %[[LIST:.+]] = firrtl.list.create %[[CAST]], %x
; CHECK-NEXT: propassign %listOfAny, %[[LIST]]

;// -----

FIRRTL version 4.0.0
; CHECK-LABEL: circuit "PublicModules"
circuit PublicModules:
; CHECK: firrtl.module @Foo
public module Foo:
; CHECK: firrtl.module private @Bar
module Bar:
; CHECK: firrtl.module @PublicModules
public module PublicModules:
13 changes: 13 additions & 0 deletions test/Dialect/FIRRTL/parse-errors.fir
Original file line number Diff line number Diff line change
Expand Up @@ -1140,3 +1140,16 @@ circuit DoubleRadix:
output d : Double
; expected-error @below {{expected floating point in Double expression}}
propassign d, Double(0hABC)

;// -----
FIRRTL version 3.9.0
circuit PublicModuleUnsupported:
; expected-error @below {{public modules are a FIRRTL 4.0.0+ feature}}
public module PublicModuleUnsupported:

;// -----
FIRRTL version 4.0.0
circuit PublicNonModule:
; expected-error @below {{only modules may be public}}
public extmodule Foo:
module PublicNonModule:

0 comments on commit 30a0274

Please sign in to comment.