Skip to content

Commit

Permalink
improve binding resolution error messages
Browse files Browse the repository at this point in the history
  • Loading branch information
zachjs committed Dec 15, 2024
1 parent 30677b3 commit 576a804
Show file tree
Hide file tree
Showing 13 changed files with 44 additions and 20 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@

### Other Enhancements

* Improved error messages for invalid port or parameter bindings
* `--write path/to/dir/` can now also be used with `--pass-through`

## v0.0.12
Expand Down
41 changes: 32 additions & 9 deletions src/Convert/ResolveBindings.hs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
{-# LANGUAGE FlexibleInstances #-}
{- sv2v
- Author: Zachary Snow <zach@zachjs.com>
-
Expand All @@ -16,12 +17,14 @@ module Convert.ResolveBindings

import Control.Monad.Writer.Strict
import Data.List (intercalate, (\\))
import Data.Maybe (isNothing)
import qualified Data.Map.Strict as Map

import Convert.Traverse
import Language.SystemVerilog.AST

type Parts = Map.Map Identifier ([(Identifier, Bool)], [Identifier])
data PartInfo = PartInfo PartKW [(Identifier, Bool)] [Identifier]
type Parts = Map.Map Identifier PartInfo

convert :: [AST] -> [AST]
convert =
Expand All @@ -30,8 +33,8 @@ convert =
(traverseDescriptions . traverseModuleItems . mapInstance)

collectPartsM :: Description -> Writer Parts ()
collectPartsM (Part _ _ _ _ name ports items) =
tell $ Map.singleton name (params, ports)
collectPartsM (Part _ _ kw _ name ports items) =
tell $ Map.singleton name $ PartInfo kw params ports
where params = parameterInfos items
collectPartsM _ = return ()

Expand All @@ -48,16 +51,17 @@ parameterInfos =
mapInstance :: Parts -> ModuleItem -> ModuleItem
mapInstance parts (Instance m paramBindings x rs portBindings) =
-- if we can't find it, just skip :(
if maybePartInfo == Nothing
if isNothing maybePartInfo
then Instance m paramBindings x rs portBindings
else Instance m paramBindings' x rs portBindings'
where
maybePartInfo = Map.lookup m parts
Just (paramInfos, portNames) = maybePartInfo
Just (PartInfo kw paramInfos portNames) = maybePartInfo
paramNames = map fst paramInfos

msg :: String -> String
msg = flip (++) $ " in instance " ++ show x ++ " of " ++ show m
msg = flip (++) $ " in instance " ++ show x ++ " of " ++ show kw ++ " "
++ show m

paramBindings' = map checkParam $
resolveBindings (msg "parameter overrides") paramNames paramBindings
Expand Down Expand Up @@ -101,22 +105,41 @@ mapInstance parts (Instance m paramBindings x rs portBindings) =

mapInstance _ other = other

class BindingArg k where
showBinding :: k -> String

instance BindingArg TypeOrExpr where
showBinding = either show show

instance BindingArg Expr where
showBinding = show

type Binding t = (Identifier, t)
-- give a set of bindings explicit names
resolveBindings :: String -> [Identifier] -> [Binding t] -> [Binding t]
resolveBindings
:: BindingArg t => String -> [Identifier] -> [Binding t] -> [Binding t]
resolveBindings _ _ [] = []
resolveBindings location available bindings@(("", _) : _) =
if length available < length bindings then
error $ "too many bindings specified for " ++ location
error $ "too many bindings specified for " ++ location ++ ": "
++ describeList "specified" (map (showBinding . snd) bindings)
++ ", but only " ++ describeList "available" (map show available)
else
zip available $ map snd bindings
resolveBindings location available bindings =
if not $ null unknowns then
error $ "unknown binding" ++ unknownsPlural ++ " "
++ unknownsStr ++ " specified for " ++ location
++ unknownsStr ++ " specified for " ++ location ++ ", "
++ describeList "available" (map show available)
else
bindings
where
unknowns = map fst bindings \\ available
unknownsPlural = if length unknowns == 1 then "" else "s"
unknownsStr = intercalate ", " $ map show unknowns

describeList :: String -> [String] -> String
describeList desc [] = "0 " ++ desc
describeList desc xs =
show (length xs) ++ " " ++ desc ++ " (" ++ xsStr ++ ")"
where xsStr = intercalate ", " xs
2 changes: 1 addition & 1 deletion test/error/binding_not_found_class.sv
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// pattern: unknown binding "R" specified for parameters in class specialization of "example"
// pattern: unknown binding "R" specified for parameters in class specialization of "example", 2 available \("P", "Q"\)
class example #(
parameter P = 1,
parameter Q = 1
Expand Down
2 changes: 1 addition & 1 deletion test/error/binding_not_found_overflow.sv
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// pattern: unknown binding "z" specified for port connections in instance "e" of "example"
// pattern: unknown binding "z" specified for port connections in instance "e" of module "example", 2 available \("x", "y"\)
module example(
input x, y
);
Expand Down
2 changes: 1 addition & 1 deletion test/error/binding_not_found_param.sv
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// pattern: unknown binding "R" specified for parameter overrides in instance "e" of "example"
// pattern: unknown binding "R" specified for parameter overrides in instance "e" of module "example", 2 available \("P", "Q"\)
module example;
parameter P = 1;
parameter Q = 1;
Expand Down
2 changes: 1 addition & 1 deletion test/error/binding_not_found_port.sv
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// pattern: unknown bindings "w", "z" specified for port connections in instance "e" of "example"
// pattern: unknown bindings "w", "z" specified for port connections in instance "e" of module "example", 2 available \("x", "y"\)
module example(
input x, y
);
Expand Down
2 changes: 1 addition & 1 deletion test/error/binding_overflow_class.sv
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// pattern: too many bindings specified for parameters in class specialization of "example"
// pattern: too many bindings specified for parameters in class specialization of "example": 3 specified \(1, 2, 3\), but only 2 available \("P", "Q"\)
class example #(
parameter P = 1,
parameter Q = 1
Expand Down
2 changes: 1 addition & 1 deletion test/error/binding_overflow_param.sv
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// pattern: too many bindings specified for parameter overrides in instance "e" of "example"
// pattern: too many bindings specified for parameter overrides in instance "e" of module "example": 3 specified \(1, 2, 3\), but only 2 available \("P", "Q"\)
module example;
parameter P = 1;
parameter Q = 1;
Expand Down
2 changes: 1 addition & 1 deletion test/error/binding_overflow_port.sv
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// pattern: too many bindings specified for port connections in instance "e" of "example"
// pattern: too many bindings specified for port connections in instance "e" of module "example": 3 specified \(1'b1, 1'b0, 1'b0\), but only 2 available \("x", "y"\)
module example(
input x, y
);
Expand Down
2 changes: 1 addition & 1 deletion test/error/interface_param_mismatch_expr.sv
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// pattern: parameter "P" in instance "intf" of "Interface" expects an expression, but was given type logic
// pattern: parameter "P" in instance "intf" of interface "Interface" expects an expression, but was given type logic
interface Interface;
parameter P = 0;
logic [P-1:0] x;
Expand Down
2 changes: 1 addition & 1 deletion test/error/interface_param_mismatch_type.sv
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// pattern: parameter "P" in instance "intf" of "Interface" expects a type, but was given expression 1
// pattern: parameter "P" in instance "intf" of interface "Interface" expects a type, but was given expression 1
interface Interface;
parameter type P;
P x;
Expand Down
2 changes: 1 addition & 1 deletion test/error/module_param_mismatch_expr.sv
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// pattern: parameter "P" in instance "mod" of "Module" expects an expression, but was given type logic
// pattern: parameter "P" in instance "mod" of module "Module" expects an expression, but was given type logic
module Module;
parameter P = 0;
logic [P-1:0] x;
Expand Down
2 changes: 1 addition & 1 deletion test/error/module_param_mismatch_type.sv
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// pattern: parameter "P" in instance "mod" of "Module" expects a type, but was given expression 1
// pattern: parameter "P" in instance "mod" of module "Module" expects a type, but was given expression 1
module Module;
parameter type P;
P x;
Expand Down

0 comments on commit 576a804

Please sign in to comment.