diff --git a/src/Convert/Interface.hs b/src/Convert/Interface.hs index 86165cf..9adbd80 100644 --- a/src/Convert/Interface.hs +++ b/src/Convert/Interface.hs @@ -6,7 +6,7 @@ module Convert.Interface (convert) where -import Data.Maybe (isJust, mapMaybe) +import Data.Maybe (mapMaybe) import Control.Monad.Writer import qualified Data.Map.Strict as Map import qualified Data.Set as Set @@ -216,10 +216,10 @@ inlineInterface (ports, items) (instanceName, instancePorts) = flip (++) portBindings $ map (traverseNestedModuleItems removeModport) $ map (traverseNestedModuleItems removeMIDeclDir) $ - map (prefixModuleItems prefix) $ - items + itemsPrefixed where prefix = instanceName ++ "_" + itemsPrefixed = map (prefixModuleItems prefix) $ items origInstancePortNames = map fst instancePorts instancePortExprs = map snd instancePorts instancePortNames = @@ -228,8 +228,7 @@ inlineInterface (ports, items) (instanceName, instancePorts) = then ports else origInstancePortNames portBindings = - map (\(ident, Just expr) -> Assign Nothing (LHSIdent ident) expr) $ - filter (isJust . snd) $ + mapMaybe portBindingItem $ zip instancePortNames instancePortExprs removeMIDeclDir :: ModuleItem -> ModuleItem @@ -240,3 +239,29 @@ inlineInterface (ports, items) (instanceName, instancePorts) = removeModport (Modport x _) = MIPackageItem $ Comment $ "removed modport " ++ x removeModport other = other + + portBindingItem :: PortBinding -> Maybe ModuleItem + portBindingItem (ident, Just expr) = + Just $ if declDirs Map.! ident == Input + then Assign Nothing (LHSIdent ident) expr + else Assign Nothing (exprToLHS expr) (Ident ident) + portBindingItem (_, Nothing) = Nothing + + declDirs = execWriter $ + mapM (collectDeclsM collectDeclDir) itemsPrefixed + collectDeclDir :: Decl -> Writer (Map.Map Identifier Direction) () + collectDeclDir (Variable dir _ ident _ _) = + if dir /= Local + then tell $ Map.singleton ident dir + else return () + collectDeclDir _ = return () + + exprToLHS :: Expr -> LHS + exprToLHS (Ident x ) = LHSIdent x + exprToLHS (Bit l e ) = LHSBit (exprToLHS l) e + exprToLHS (Range l m r) = LHSRange (exprToLHS l) m r + exprToLHS (Dot l x ) = LHSDot (exprToLHS l) x + exprToLHS (Concat ls ) = LHSConcat $ map exprToLHS ls + exprToLHS other = + error $ "trying to bind (part of) an interface output to " ++ + show other ++ " but that can't be an LHS" diff --git a/test/relong/complex_interface.sv b/test/relong/complex_interface.sv new file mode 100644 index 0000000..61c01d2 --- /dev/null +++ b/test/relong/complex_interface.sv @@ -0,0 +1,49 @@ +interface CacheSetInterface( + input logic [7:0] request, + output logic [7:0] response +); + + modport CacheSet( + input request, + output response + ); + +endinterface + +module CacheWithInterface( + input logic [7:0] dataIn, + output logic [7:0] dataOut, + input logic clock, clear +); + + logic [7:0] myRequest; + logic [7:0] myResponse; + + CacheSetInterface dataInterface( + .request(myRequest), + .response(myResponse) + ); + + CacheSet set( + .data(dataInterface.CacheSet), + .clock, + .clear + ); + + assign myRequest = dataIn; + assign dataOut = myResponse; + +endmodule + +module CacheSet ( + CacheSetInterface.CacheSet data, + input logic clock, clear +); + + always_ff @(posedge clock) + if(clear) + data.response <= 8'h0; + else + data.response <= ~data.request; + +endmodule \ No newline at end of file diff --git a/test/relong/complex_interface.v b/test/relong/complex_interface.v new file mode 100644 index 0000000..b7cd0a4 --- /dev/null +++ b/test/relong/complex_interface.v @@ -0,0 +1,59 @@ +// interface CacheSetInterface( +// input logic [7:0] request, +// output logic [7:0] response +// ); + +// modport CacheSet( +// input request, +// output response +// ); + +// endinterface + +module CacheWithInterface( + input wire [7:0] dataIn, + output wire [7:0] dataOut, + input wire clock, clear +); + + wire [7:0] myRequest; + wire [7:0] myResponse; + + // CacheSetInterface dataInterface( + // .request(myRequest), + // .response(myResponse) + // ); + + wire [7:0] dataInterface_request; + wire [7:0] dataInterface_response; + generate + assign dataInterface_request = myRequest; + // dataInterface.myResponse is an output + assign myResponse = dataInterface_response; + endgenerate + + CacheSet set( + .data_request(dataInterface_request), + .data_response(dataInterface_response), + .clock(clock), + .clear(clear) + ); + + assign myRequest = dataIn; + assign dataOut = myResponse; + +endmodule + +module CacheSet ( + input wire [7:0] data_request, + output reg [7:0] data_response, + input wire clock, clear +); + + always @(posedge clock) + if(clear) + data_response <= 8'h0; + else + data_response <= ~data_request; + +endmodule \ No newline at end of file diff --git a/test/relong/complex_interface_tb.v b/test/relong/complex_interface_tb.v new file mode 100644 index 0000000..37376d8 --- /dev/null +++ b/test/relong/complex_interface_tb.v @@ -0,0 +1,39 @@ +`default_nettype none + +module top; + + reg [8:0] dataIn; + wire [7:0] dataOut; + reg clock, clear; + + + CacheWithInterface dut( + .dataIn(dataIn[7:0]), + .dataOut(dataOut), + .clock(clock), + .clear(clear) + ); + + initial begin + clock = 1; + forever #5 clock = ~clock; + end + + reg [7:0] last; + initial begin + $monitor($time, " %h -> %h [%h]", dataIn, dataOut, last); + clear = 1'b1; + last = 8'h0; + dataIn = 8'h0; + repeat (3) @(posedge clock); + clear = 1'b0; + for (dataIn = 8'h0; dataIn <= 9'hff; dataIn = dataIn + 8'h1) begin + @(posedge clock); + if (~dataOut != last) + $error("Mismatch"); + last = last + 8'h1; + end + $finish; + end +endmodule +