Commit 67466eaa by Zachary Snow

major interface conversion update

- module instances with modport bindings are now inlined
- support for modports in generate loops
- support for generic interfaces
- implied modport instance propagation
- add error message for interface instances missing port list
parent 5161a9e7
......@@ -39,6 +39,7 @@ module Convert.Scoper
, embedScopes
, withinProcedure
, withinProcedureM
, scopeModuleItemT
) where
import Control.Monad.State
......@@ -254,6 +255,20 @@ evalScoperT declMapper moduleItemMapper genItemMapper stmtMapper topName items =
return items'
initialState = Scopes [] Map.empty False []
wrappedModuleItemMapper = scopeModuleItemT
declMapper moduleItemMapper genItemMapper stmtMapper
scopeModuleItemT
:: forall a m. Monad m
=> MapperM (ScoperT a m) Decl
-> MapperM (ScoperT a m) ModuleItem
-> MapperM (ScoperT a m) GenItem
-> MapperM (ScoperT a m) Stmt
-> ModuleItem
-> ScoperT a m ModuleItem
scopeModuleItemT declMapper moduleItemMapper genItemMapper stmtMapper =
wrappedModuleItemMapper
where
fullStmtMapper :: Stmt -> ScoperT a m Stmt
fullStmtMapper (Block kw name decls stmts) = do
enterScope name ""
......
......@@ -597,10 +597,9 @@ traverseExprsM exprMapper = moduleItemMapper
genItemMapper = traverseGenItemExprsM exprMapper
modportDeclMapper (dir, ident, t, e) = do
t' <- typeMapper t
modportDeclMapper (dir, ident, e) = do
e' <- exprMapper e
return (dir, ident, t', e')
return (dir, ident, e')
traverseExprs :: Mapper Expr -> Mapper ModuleItem
traverseExprs = unmonad traverseExprsM
......@@ -942,11 +941,6 @@ traverseTypesM' strategy mapper =
then mapper t >>= \t' -> return (i, Left t')
else return (i, Left t)
mapParam (i, Right e) = return $ (i, Right e)
miMapper (Modport name decls) =
mapM mapModportDecl decls >>= return . Modport name
where
mapModportDecl (d, x, t, e) =
mapper t >>= \t' -> return (d, x, t', e)
miMapper other = return other
traverseTypes' :: TypeStrategy -> Mapper Type -> Mapper ModuleItem
......
......@@ -62,6 +62,11 @@ exprToLHS (Dot l x ) = do
exprToLHS (Concat ls ) = do
ls' <- mapM exprToLHS ls
Just $ LHSConcat ls'
exprToLHS (Pattern ls ) = do
ls' <- mapM exprToLHS $ map snd ls
if all (null . fst) ls
then Just $ LHSConcat ls'
else Nothing
exprToLHS (Stream o e ls) = do
ls' <- mapM exprToLHS ls
Just $ LHSStream o e ls'
......
......@@ -28,7 +28,7 @@ import Language.SystemVerilog.AST.Expr (Expr(Nil), pattern Ident, Range, showRan
import Language.SystemVerilog.AST.GenItem (GenItem)
import Language.SystemVerilog.AST.LHS (LHS)
import Language.SystemVerilog.AST.Stmt (Stmt, AssertionItem, Timing(Delay))
import Language.SystemVerilog.AST.Type (Type, Identifier, DriveStrength)
import Language.SystemVerilog.AST.Type (Identifier, DriveStrength)
data ModuleItem
= MIAttr Attr ModuleItem
......@@ -90,14 +90,14 @@ showGate kw d x args =
nameStr = showPad $ Ident x
showModportDecl :: ModportDecl -> String
showModportDecl (dir, ident, t, e) =
showModportDecl (dir, ident, e) =
if e == Ident ident
then printf "%s %s" (show dir) ident
else printf "%s .%s(/* type: %s */ %s)" (show dir) ident (show t) (show e)
else printf "%s .%s(%s)" (show dir) ident (show e)
type PortBinding = (Identifier, Expr)
type ModportDecl = (Direction, Identifier, Type, Expr)
type ModportDecl = (Direction, Identifier, Expr)
data AlwaysKW
= Always
......
......@@ -577,9 +577,9 @@ ParamAsgn :: { Decl }
: Identifier "=" Expr { Param Parameter (Implicit Unspecified []) $1 $3 }
PortDecls :: { ([Identifier], [ModuleItem]) }
: "(" DeclTokens(")") { parseDTsAsPortDecls $2 }
| "(" ")" { ([], []) }
| {- empty -} { ([], []) }
: "(" PortDeclTokens(")") { parseDTsAsPortDecls $2 }
| "(" ")" { ([], []) }
| {- empty -} { ([], []) }
ModportItems :: { [(Identifier, [ModportDecl])] }
: ModportItem { [$1] }
......@@ -592,7 +592,7 @@ ModportPortsDeclarations :: { [ModportDecl] }
ModportPortsDeclaration(delim) :: { [ModportDecl] }
: ModportSimplePortsDeclaration(delim) { $1 }
ModportSimplePortsDeclaration(delim) :: { [ModportDecl] }
: Direction ModportSimplePorts delim { map (\(a, b) -> ($1, a, TypeOf b, b)) $2 }
: Direction ModportSimplePorts delim { map (\(a, b) -> ($1, a, b)) $2 }
ModportSimplePorts :: { [(Identifier, Expr)] }
: ModportSimplePort { [$1] }
| ModportSimplePorts "," ModportSimplePort { $1 ++ [$3] }
......@@ -611,11 +611,13 @@ Identifiers :: { [Identifier] }
-- uses delimiter propagation hack to avoid conflicts
DeclTokens(delim) :: { [DeclToken] }
: DeclToken delim { [$1] }
| DeclToken DeclTokens(delim) { [$1] ++ $2 }
| Identifier ParamBindings DeclTokens(delim) {% posInject \p -> [DTIdent p $1, DTParams p $2] ++ $3 }
| DeclTokenAsgn "," DeclTokens(delim) {% posInject \p -> [$1, DTComma p] ++ $3 }
| DeclTokenAsgn delim {% posInject \p -> [$1] }
: DeclTokensBase(DeclTokens(delim), delim) { $1 }
DeclTokensBase(repeat, delim) :: { [DeclToken] }
: DeclToken delim { [$1] }
| DeclToken repeat { [$1] ++ $2 }
| Identifier ParamBindings repeat {% posInject \p -> [DTIdent p $1, DTParams p $2] ++ $3 }
| DeclTokenAsgn "," repeat {% posInject \p -> [$1, DTComma p] ++ $3 }
| DeclTokenAsgn delim {% posInject \p -> [$1] }
DeclToken :: { DeclToken }
: "," {% posInject \p -> DTComma p }
| "[" "]" {% posInject \p -> DTAutoDim p }
......@@ -640,6 +642,12 @@ DeclToken :: { DeclToken }
DeclTokenAsgn :: { DeclToken }
: "=" opt(DelayOrEvent) Expr {% posInject \p -> DTAsgn p AsgnOpEq $2 $3 }
| AsgnBinOp Expr {% posInject \p -> DTAsgn p $1 Nothing $2 }
PortDeclTokens(delim) :: { [DeclToken] }
: DeclTokensBase(PortDeclTokens(delim), delim) { $1 }
| GenericInterfaceDecl PortDeclTokens(delim) { $1 ++ $2}
| GenericInterfaceDecl delim { $1 }
GenericInterfaceDecl :: { [DeclToken] }
: "interface" Identifier {% posInject \p -> [DTType p (\Unspecified -> InterfaceT "" Nothing), DTIdent p $2] }
VariablePortIdentifiers :: { [(Identifier, Expr)] }
: VariablePortIdentifier { [$1] }
......
interface bundle;
logic [1:0] index;
logic clock;
logic [3:0] inp;
logic [1:0] index = 0;
logic clock = 0;
logic [3:0] inp = '1;
logic out;
endinterface
module rotator(bundle b);
initial b.index = 0;
always @(posedge b.clock)
b.index <= b.index + 1;
endmodule
module setter(bundle b);
initial b.inp = '1;
always @(posedge b.clock)
b.inp[b.index] <= b.out;
endmodule
......@@ -23,7 +21,6 @@ endmodule
module clocker(bundle b);
initial begin
b.clock <= 0;
forever
#5 b.clock <= ~b.clock;
end
......
module impl(b_index, b_clock, b_inp, b_out);
output reg [1:0] b_index;
output reg b_clock;
output reg [3:0] b_inp;
output wire b_out;
module impl;
reg [1:0] b_index;
reg b_clock;
reg [3:0] b_inp;
wire b_out;
initial b_index = 0;
always @(posedge b_clock)
......@@ -19,15 +19,6 @@ module impl(b_index, b_clock, b_inp, b_out);
forever
#5 b_clock <= ~b_clock;
end
endmodule
module top;
wire [1:0] b_index;
wire b_clock;
wire [3:0] b_inp;
wire b_out;
impl impl(b_index, b_clock, b_inp, b_out);
initial begin
$monitor("%b %b %b %b", b_index, b_clock, b_inp, b_out);
......@@ -36,3 +27,6 @@ module top;
end
endmodule
module top;
impl impl();
endmodule
interface Interface #(num_clients = 0);
bit [num_clients-1:0] req;
for (genvar i = 0; i < num_clients; ++i) begin : mps
modport client_mp (output .client_req(req[i]));
end
endinterface
module ClientAnd (client_ifc, bits);
parameter WIDTH = 2;
Interface client_ifc;
input [WIDTH-1:0] bits;
assign client_ifc.client_req = &bits;
endmodule
module ClientTick #(start = 0, period = 1) (Interface client_ifc, input clock);
initial client_ifc.client_req = start;
integer counter;
initial counter = 0;
always @(posedge clock) begin
counter += 1;
if (counter % period == 0)
client_ifc.client_req = ~client_ifc.client_req;
end
endmodule
module top;
logic clock;
initial begin
clock = 1;
forever #1 clock = ~clock;
end
parameter N = 8;
Interface #(.num_clients(N)) intf();
for (genvar j = 0; j < N - 1; j++) begin : clients
ClientTick #(j, j + 1) client(
.clock,
.client_ifc(intf.mps[j + 1].client_mp)
);
end
ClientAnd #(4) client(
.bits(intf.req[4:1]),
.client_ifc(intf.mps[0].client_mp)
);
initial begin
$monitor("%0d %b %b", $time, clock, intf.req);
#100 $finish;
end
endmodule
module ClientAnd (client_req, bits);
parameter WIDTH = 2;
output client_req;
input [WIDTH-1:0] bits;
assign client_req = &bits;
endmodule
module ClientTick #(
parameter start = 0,
parameter period = 1
) (
output reg client_req,
input clock
);
initial client_req = start;
integer counter;
initial counter = 0;
always @(posedge clock) begin
counter += 1;
if (counter % period == 0)
client_req = ~client_req;
end
endmodule
module top;
reg clock;
initial begin
clock = 1;
forever #1 clock = ~clock;
end
parameter N = 8;
generate
begin : intf
wire [N-1:0] req;
end
genvar j;
for (j = 0; j < N - 1; j = j + 1) begin : clients
ClientTick #(j, j + 1) client(
.clock,
.client_req(intf.req[j + 1])
);
end
endgenerate
ClientAnd #(4) client(
.bits(intf.req[4:1]),
.client_req(intf.req[0])
);
initial begin
$monitor("%0d %b %b", $time, clock, intf.req);
#100 $finish;
end
endmodule
interface InterfaceA;
task hello;
input integer inp;
$display("Hello from InterfaceA %0d", inp);
endtask
logic [20:0] x = 21'b01011_00100000_01011110;
endinterface
interface InterfaceB;
task hello;
input integer inp;
$display("Hello from InterfaceB %0d", inp);
endtask
logic [10:0] x = 11'b011_11110100;
endinterface
// could get bound to any of the interfaces or modports
module Module(interface i);
initial #4 i.hello(1);
initial #5 $display("Module got %b", i.x);
endmodule
interface InterfaceM;
logic [4:0] x = 0;
task hello;
input integer inp;
x = x + 1;
$display("Hello from InterfaceM %0d %b", inp, x);
endtask
modport A(input .x(x[0]));
modport B(input .x(x[2:1]));
endinterface
// could get bound to the entire interface bundle, or either modport
module ModuleM(InterfaceM i);
initial i.hello(-1);
initial $display("ModuleM got %b", i.x);
endmodule
module ModuleWrapperMA(InterfaceM.A i); Module m(i); endmodule
module ModuleWrapperMB(InterfaceM.B i); Module m(i); endmodule
module ModuleWrapperM (InterfaceM i); Module m(i); endmodule
module ModuleMWrapperMA(InterfaceM.A i); ModuleM m(i); endmodule
module ModuleMWrapperMB(InterfaceM.B i); ModuleM m(i); endmodule
module ModuleMWrapperM (InterfaceM i); ModuleM m(i); endmodule
module top;
InterfaceM im();
Module c(im.A);
Module d(im.B);
Module e(im);
ModuleM x(im.A);
ModuleM y(im.B);
ModuleM z(im);
InterfaceA ia();
InterfaceB ib();
Module a(ia);
Module b(ib);
ModuleWrapperMA cw(im);
ModuleWrapperMB dw(im);
ModuleWrapperM ew(im);
ModuleMWrapperMA xw(im);
ModuleMWrapperMB yw(im);
ModuleMWrapperM zw(im);
endmodule
module impl;
reg [4:0] im_x = 0;
task im_hello;
input integer inp;
begin
im_x = im_x + 1;
$display("Hello from InterfaceM %0d %b", inp, im_x);
end
endtask
initial #4 im_hello(1);
initial #5 $display("Module got %b", im_x[0]);
initial #4 im_hello(1);
initial #5 $display("Module got %b", im_x[2:1]);
initial #4 im_hello(1);
initial #5 $display("Module got %b", im_x);
initial im_hello(-1);
initial $display("ModuleM got %b", im_x[0]);
initial im_hello(-1);
initial $display("ModuleM got %b", im_x[2:1]);
initial im_hello(-1);
initial $display("ModuleM got %b", im_x);
task ia_hello;
input integer inp;
$display("Hello from InterfaceA %0d", inp);
endtask
wire [20:0] ia_x = 21'b01011_00100000_01011110;
task ib_hello;
input integer inp;
$display("Hello from InterfaceB %0d", inp);
endtask
wire [10:0] ib_x = 11'b011_11110100;
initial #4 ia_hello(1);
initial #5 $display("Module got %b", ia_x);
initial #4 ib_hello(1);
initial #5 $display("Module got %b", ib_x);
initial #4 im_hello(1);
initial #5 $display("Module got %b", im_x[0]);
initial #4 im_hello(1);
initial #5 $display("Module got %b", im_x[2:1]);
initial #4 im_hello(1);
initial #5 $display("Module got %b", im_x);
initial im_hello(-1);
initial $display("ModuleM got %b", im_x[0]);
initial im_hello(-1);
initial $display("ModuleM got %b", im_x[2:1]);
initial im_hello(-1);
initial $display("ModuleM got %b", im_x);
endmodule
module top;
impl impl();
endmodule
module Module(input wire x);
initial $display("Module %d", x);
endmodule
module top;
wire i_x = 0;
genvar g;
localparam SOME_VAL = 3;
initial $display("Interface %d %d", i_x, SOME_VAL);
Module m(.x(i_x));
generate
genvar g;
for (g = 10; g < 15; g = g + 1) begin
initial $display(g);
begin : i
wire x = 0;
initial $display("Interface %d %d", x, SOME_VAL);
for (g = 10; g < 15; g = g + 1) begin
initial $display(g);
end
end
for (g = 0; g < 5; g = g + 1) begin
initial $display(g);
endgenerate
generate
begin : m
initial $display("Module %d", i.x);
for (g = 0; g < 5; g = g + 1) begin
initial $display(g);
end
end
endgenerate
endmodule
......@@ -20,8 +20,8 @@ module ModuleA(Interface.ModportA m);
endmodule
module ModuleB(Interface.ModportB m);
parameter WIDTH = 0;
initial m.x = 1;
localparam WIDTH = 2 * m.WIDTH;
always @(posedge m.clock) begin
logic temp;
temp = m.x[WIDTH-1];
......@@ -33,7 +33,10 @@ module ModuleB(Interface.ModportB m);
endmodule
module ModuleBWrapper(Interface.ModportB m);
ModuleB b(m);
parameter WIDTH = 0;
ModuleB #(WIDTH) b(m);
integer i = 0;
initial #1 $display("shadow i = %d, %b", i, m.x);
endmodule
module ModuleAWrapper(Interface.ModportA m);
......@@ -45,7 +48,7 @@ module Tester(input clock);
logic [WIDTH-1:0] idx1, idx2;
Interface #(2 ** WIDTH) i(clock, '{idx1, idx2});
ModuleAWrapper a(i);
ModuleBWrapper b(i);
ModuleBWrapper #(2 * 2 ** WIDTH) b(i);
always @(negedge clock)
$display("%d %0d %2d %2d %b", $time, WIDTH, idx1, idx2, i.x);
endmodule
......@@ -10,6 +10,9 @@ module Tester(input clock);
assign idx1 = $clog2(x[2*DATA_WIDTH-1:DATA_WIDTH]);
assign idx2 = $clog2(x[DATA_WIDTH-1:0]);
integer i = 0;
initial #1 $display("shadow i = %d, %b", i, x);
always @(posedge clock) begin : block
localparam SIZE = 2 * DATA_WIDTH;
integer i;
......
interface InterfaceA;
logic x;
modport M(input x);
endinterface
interface InterfaceB;
logic y;
modport N(input y);
endinterface
module ModuleA(modport_a);
InterfaceA modport_a;
initial $display("ModuleA %b", modport_a.x);
endmodule
module ModuleB(modport_b);
InterfaceB modport_b;
InterfaceA interface_a();
ModuleA module_a(interface_a.M);
initial $display("ModuleB %b", modport_b.y);
assign interface_a.x = 0;
endmodule
module ModuleC;
InterfaceB interface_b();
ModuleB module_b(interface_b.N);
assign interface_b.y = 1;
endmodule
module top;
ModuleC module_c();
endmodule
module ModuleC;
wire y;
assign y = 1;
initial $display("ModuleB %b", y);
wire x;
assign x = 0;
initial $display("ModuleA %b", x);
endmodule
module top;
ModuleC module_c();
endmodule
module top;
wire x, f_x;
wire f_a_x, f_b_x;
assign x = 1;
assign f_x = x;
assign f_a_x = x;
assign f_b_x = ~x;
initial begin
$display("bar got %b", f_a_x);
$display("bar got %b", f_b_x);
end
wire x = 1;
generate
begin : f
wire x;
begin : a
wire x;
initial begin
$display("bar got %b", x);
end
end
assign a.x = x;
begin : b
wire x;
initial begin
$display("bar got %b", x);
end
end
assign b.x = ~x;
end
assign f.x = x;
endgenerate
endmodule
......@@ -12,10 +12,16 @@ module M(data);
endmodule
module top;
wire [31:0] x_data = 0;
wire [9:0] y_data = 0;
M #(.WIDTH(32)) a(x_data);
M #(.WIDTH(10)) b(y_data);
M #(3, 32, 4) c(x_data);
M #(5, 10, 6) d(y_data);
generate
begin : x
wire [31:0] data = 0;
end
begin : y
wire [9:0] data = 0;
end
endgenerate
M #(.WIDTH(32)) a(x.data);
M #(.WIDTH(10)) b(y.data);
M #(3, 32, 4) c(x.data);
M #(5, 10, 6) d(y.data);
endmodule
typedef struct packed { logic x; } T;
interface Interface;
integer x;
function z;
input x;
z = ~x;
endfunction
endinterface
module Module(interface y);
function z;
input T y;
z = y.x;
endfunction
integer x = 0;
initial begin
#1;
$display("x = %b", x);
$display("z(x) = %b", z(x));
$display("y.x = %b", y.x);
$display("y.z(x) = %b", y.z(x));
$display("y.z(y.x) = %b", y.z(y.x));
$display("y.z(z(y.x)) = %b", y.z(z(y.x)));
end
endmodule
module top;
Interface x();
initial x.x = 1;
Module y(x);
endmodule
module top;
generate
begin : x
integer x;
function z;
input x;
z = ~x;
endfunction
end
endgenerate
initial x.x = 1;
generate
begin : y
function z;
input x;
z = x;
endfunction
integer x = 0;
initial begin
#1;
$display("x = %b", x);
$display("z(x) = %b", z(x));
$display("y.x = %b", top.x.x);
$display("y.z(x) = %b", top.x.z(x));
$display("y.z(y.x) = %b", top.x.z(top.x.x));
$display("y.z(z(y.x)) = %b", top.x.z(z(top.x.x)));
end
end
endgenerate
endmodule
module top;
wire [3:0] i_x;
reg [1:0] i_w;
assign i_x = 4'b1001;
initial i_w = 2'b10;
generate
begin : i
wire [3:0] x;
reg [1:0] w;
end
endgenerate
assign i.x = 4'b1001;
initial i.w = 2'b10;
initial begin
$display("%b", i_x[3]);
$display("%b", i_x[2]);
$display("%b", i_x[1]);
$display("%b", i_x[0]);
$display("%b", i.x[3]);
$display("%b", i.x[2]);
$display("%b", i.x[1]);
$display("%b", i.x[0]);
end
endmodule
......@@ -25,7 +25,7 @@ module top;
clear = 1'b1;
last = 8'h0;
dataIn = 8'h0;
repeat (3) @(posedge clock);
repeat (4) @(posedge clock);
clear = 1'b0;
for (dataIn = 8'h0; dataIn <= 9'hff; dataIn = dataIn + 8'h1) begin
@(posedge clock);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment