From 638fa5b4e6236a172224a6aef72063040b3af00c Mon Sep 17 00:00:00 2001 From: Tom Clarke Date: Thu, 15 Aug 2024 23:26:02 +0100 Subject: [PATCH] fix: more wavesim bugs fix: exception in value column width estimation code fix: possible oscillation when ShownCycles determination is not stable Cosmetic changes to zoom button --- public/index.html | 2 +- src/Renderer/UI/MainView.fs | 2 +- src/Renderer/UI/WaveSim/WaveSim.fs | 6 ++--- src/Renderer/UI/WaveSim/WaveSimNavigation.fs | 26 +++++++++++--------- src/Renderer/UI/WaveSim/WaveSimStyle.fs | 4 ++- src/Renderer/UI/WaveSim/WaveSimWaveforms.fs | 8 +++--- 6 files changed, 25 insertions(+), 23 deletions(-) diff --git a/public/index.html b/public/index.html index 248c1eaa2..7b8b714ac 100644 --- a/public/index.html +++ b/public/index.html @@ -4,6 +4,6 @@ -
+
diff --git a/src/Renderer/UI/MainView.fs b/src/Renderer/UI/MainView.fs index b759186a7..130c1d768 100644 --- a/src/Renderer/UI/MainView.fs +++ b/src/Renderer/UI/MainView.fs @@ -391,7 +391,7 @@ let displayView model dispatch = UserSelect UserSelectOptions.None BorderTop "2px solid lightgray" BorderBottom "2px solid lightgray" - OverflowX OverflowOptions.Auto + CSSProp.Custom("Overflow", "clip clip") Height "calc(100%-4px)" ] ] [ diff --git a/src/Renderer/UI/WaveSim/WaveSim.fs b/src/Renderer/UI/WaveSim/WaveSim.fs index eb9084435..c568c8292 100644 --- a/src/Renderer/UI/WaveSim/WaveSim.fs +++ b/src/Renderer/UI/WaveSim/WaveSim.fs @@ -166,8 +166,8 @@ let rec refreshWaveSim (newSimulation: bool) (wsModel: WaveSimModel) (model: Mod | Some sp -> updateSpinner (fst sp) (snd sp) numToDo model |> updateWSModel (fun _ -> ws) - model, Elmish.Cmd.none - |> TimeHelpers.instrumentInterval "refreshWaveSim" start) + model, Elmish.Cmd.none) + //|> TimeHelpers.instrumentInterval "refreshWaveSim" start) //} /// Refresh the state of the wave simulator according to the model and canvas state. @@ -340,7 +340,7 @@ let viewWaveSim canvasState (model: Model) dispatch : ReactElement = [WaveSimRams.ramTables wsModel] ) - div [] [ + div [Style [OverflowX OverflowOptions.Clip]] [ WaveSimSelect.selectRamModal wsModel dispatch WaveSimSelect.selectWavesModal wsModel dispatch div [ viewWaveSimStyle ] diff --git a/src/Renderer/UI/WaveSim/WaveSimNavigation.fs b/src/Renderer/UI/WaveSim/WaveSimNavigation.fs index bf936f69a..9a13f9f21 100644 --- a/src/Renderer/UI/WaveSim/WaveSimNavigation.fs +++ b/src/Renderer/UI/WaveSim/WaveSimNavigation.fs @@ -76,6 +76,10 @@ let inline updateViewerWidthInWaveSim w (model:Model) = let wholeCycles = max 1 (int (float waveColWidth / singleWaveWidth wsModel)) |> min (Constants.maxLastClk / wsModel.CycleMultiplier) // make sure there can be no over-run when making viewer larger + // prevent oscilaltion when number of cycles changes continuously due to width changes in values (rare corner case) + |> (function | whole when abs (float (whole - wsModel.ShownCycles) / float wsModel.ShownCycles) < 0.1 -> wsModel.ShownCycles + | whole -> whole) + let singleCycleWidth = float waveColWidth / float wholeCycles let finalWavesColWidth = singleCycleWidth * float wholeCycles @@ -110,26 +114,21 @@ let inline setViewerWidthInWaveSim w dispatch = let rec validateSimParas (ws: WaveSimModel) = if ws.StartCycle < 0 then - printfn $"ERROR in Sim parameters: StartCycle {ws.StartCycle} < 0" validateSimParas {ws with StartCycle = 0} elif ws.CurrClkCycleDetail > Constants.maxLastClk then validateSimParas {ws with CurrClkCycleDetail = Constants.maxLastClk} elif (ws.StartCycle + ws.ShownCycles-1)*ws.CycleMultiplier > Constants.maxLastClk then - printfn $"Correcting sim paras by reducing StartCycle" {ws with StartCycle = Constants.maxLastClk / ws.CycleMultiplier - ws.ShownCycles} elif ws.CurrClkCycle < ws.StartCycle || ws.CurrClkCycle >= ws.StartCycle + ws.ShownCycles then - printfn $"Resetting CurClkCycle which {ws.CurrClkCycle} was too large with multiplier = {ws.CycleMultiplier}" {ws with CurrClkCycle = ws.StartCycle; CurrClkCycleDetail = ws.StartCycle*ws.CycleMultiplier} else ws |> validateScrollBarInfo let changeMultiplier newMultiplier (ws: WaveSimModel) = let oldM = ws.CycleMultiplier - printfn $"Old: {oldM} shown {ws.ShownCycles} start={ws.StartCycle} NewM={newMultiplier}" let sampsHalf = (float ws.ShownCycles - 1.) / 2. let newShown = 1 + min ws.ShownCycles (Constants.maxLastClk / newMultiplier) let newStart = int ((float ws.StartCycle + sampsHalf) * float oldM / float newMultiplier - (float newShown - 1.) / 2.) - printfn $"New: shown={newShown} start = {newStart}" {ws with ShownCycles = newShown; StartCycle = newStart; CycleMultiplier = newMultiplier} |> validateSimParas @@ -319,7 +318,7 @@ let makeScrollbar (wsm: WaveSimModel) (dispatch: Msg->unit): ReactElement = OnMouseDown tbMouseDownHandler; OnMouseUp tbMouseUpHandler; OnMouseMove tbMouseMoveHandler; ] - div [ Style [ MarginTop "5px"; MarginBottom "5px"; Height "25px"]] [ + div [ Style [ WhiteSpace WhiteSpaceOptions.Nowrap; MarginTop "5px"; MarginBottom "5px"; Height "25px"; CSSProp.Custom("Overflow", "visible visible")]] [ button [ Button.Props [scrollbarClkCycleLeftStyle] ] (fun _ -> scrollWaveformViewBy -1.0) (str "◀") @@ -438,7 +437,7 @@ let multiplierMenuButton(wsModel: WaveSimModel) (dispatch: Msg -> unit) = /// key = 0 .. n-1 where there are n possible multipliers let mulTable = Constants.multipliers let menuItem (key) = - let itemLegend = str (match key with | 0 -> "Every Cycle (normal)" | _ -> $"Every {mulTable[key]} cycles") + let itemLegend = str (match key with | 0 -> "Every Cycle (normal X1)" | _ -> $"Every {mulTable[key]} cycles") Menu.Item.li [ Menu.Item.IsActive (Constants.multipliers[key] = wsModel.CycleMultiplier) Menu.Item.OnClick (fun _ -> @@ -446,17 +445,20 @@ let multiplierMenuButton(wsModel: WaveSimModel) (dispatch: Msg -> unit) = dispatch ClosePopup) ] [ itemLegend ] + let addSpaces n r = span [Style[PaddingLeft n; PaddingRight n]] [r] let menu = div [] [ - p [Style[ Color IColor.IsDanger; FontWeight 600; FontSize "18px"]] [str "Warning: zoom greater than X1 will sample the waveform and lose information about fast-changing outputs"] + p [Style[ Color "darkred"; FontWeight 600; FontSize "18px"]] [str "Warning: zoom greater than X1 will sample the waveform and lose information about fast-changing outputs"] br [] - p [] [str "Use it to observe slow-changing signals when the normal zoom range is not enough."] + p [] [str "Use it this menu to zoom out slow-changing signals when the range of"; addSpaces 5 zoomOutSVG; str "is not enough."] br [] Menu.menu [] [ Menu.list [] (List.map menuItem [0 .. mulTable.Length - 1 ])] ] let buttonClick = Button.OnClick (fun _ -> - printfn $"Mul={wsModel.CycleMultiplier}" - dispatch <| ShowStaticInfoPopup("Extra Zoom Sampling Rate",menu,dispatch )) - Button.button ( buttonClick :: topHalfButtonProps IColor.IsDanger "ZoomButton" false) [str $"Extra zoom X{wsModel.CycleMultiplier}"] + dispatch <| ShowStaticInfoPopup("Zoom Sampling Rate",menu,dispatch )) + let expectedMaxShown = int (wsModel.WaveformColumnWidth / float Constants.minCycleWidth) + if wsModel.ShownCycles = expectedMaxShown || wsModel.CycleMultiplier > 1 then + Button.button ( buttonClick :: topHalfButtonProps IColor.IsDanger "ZoomButton" false) [str $"X{wsModel.CycleMultiplier}"] + else str "" diff --git a/src/Renderer/UI/WaveSim/WaveSimStyle.fs b/src/Renderer/UI/WaveSim/WaveSimStyle.fs index 4efa62526..6d0c280d5 100644 --- a/src/Renderer/UI/WaveSim/WaveSimStyle.fs +++ b/src/Renderer/UI/WaveSim/WaveSimStyle.fs @@ -573,7 +573,8 @@ let valuesColumnSize wsModel = |> List.max let sampleVals = [maxValueBusWidth; min maxValueBusWidth NumberHelpers.Constants.maxBinaryDisplayWidth] - |> List.map (fun num -> + |> List.map (fun num -> + let num = min (max num 1) (SimulatorTypes.bigIntMaskA.Length - 2) let worstCaseVal, extra = match wsModel.Radix with | CommonTypes.Hex | CommonTypes.Bin -> 0I, 2. @@ -780,6 +781,7 @@ let radixTabAStyle = Style [ let radixTabsStyle = Style [ Height Constants.rowHeight FontSize "80%" + OverflowX OverflowOptions.Clip Display DisplayOptions.Inline ] diff --git a/src/Renderer/UI/WaveSim/WaveSimWaveforms.fs b/src/Renderer/UI/WaveSim/WaveSimWaveforms.fs index 7a30ef344..635466698 100644 --- a/src/Renderer/UI/WaveSim/WaveSimWaveforms.fs +++ b/src/Renderer/UI/WaveSim/WaveSimWaveforms.fs @@ -173,7 +173,7 @@ let namesColumn model wsModel dispatch : ReactElement = nameRows model wsModel dispatch div (namesColumnProps wsModel) (List.concat [ topRow []; rows ]) - |> TimeHelpers.instrumentInterval "namesColumn" start + //|> TimeHelpers.instrumentInterval "namesColumn" start /// Create label of waveform value for each selected wave at a given clk cycle. @@ -220,11 +220,9 @@ let private valuesColumn wsModel : ReactElement = let width, rows = valueRows wsModel let cursorClkNum = wsModel.CurrClkCycleDetail let topRowNumber = [ div [Style [FontSize "10pt" ; VerticalAlign "bottom"; FontWeight "bold"; PaddingLeft "4pt"]] [str (string <| cursorClkNum)] ] - printfn "%A" topRowNumber - div [ HTMLAttr.Id "ValuesCol" ; valuesColumnStyle width] (List.concat [ topRow topRowNumber ; rows ]) - |> TimeHelpers.instrumentInterval "valuesColumn" start + //|> TimeHelpers.instrumentInterval "valuesColumn" start /// Generate a column of waveforms corresponding to selected waves. let waveformColumn (wsModel: WaveSimModel) dispatch : ReactElement = @@ -270,7 +268,7 @@ let showWaveforms (model: Model) (wsModel: WaveSimModel) (dispatch: Msg -> unit) else $"min( calc(100vh - {fixedHeight}px) , {wHeight}px)" - div [ HTMLAttr.Id "Scroller"; Style [ Height cssHeight; Width "100%"; CSSProp.Custom("overflow", "auto")]] [ + div [ HTMLAttr.Id "Scroller"; Style [ Height cssHeight; Width "100%"; CSSProp.Custom("overflow", "hidden auto")]] [ div [ HTMLAttr.Id "WaveCols" ;showWaveformsStyle ] [ namesColumn model wsModel dispatch